package com.minelx.woods.task.core;

import com.minelx.statementsplus.cha.base.ChaSession;
import com.minelx.woods.task.common.Node;
import com.minelx.util.multithread.ITask;
import com.minelx.util.multithread.IWorker;
import com.minelx.util.multithread.IWorking;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static java.util.stream.Collectors.toList;

public class PostTreeTaskService implements AutoCloseable {

	private final SqlTaskValuesHandler sqlTaskValuesHandler;

	// post execution service
	private final ExecutorService service;

	private final IWorker leafTaskWorker;

	public PostTreeTaskService(ChaSession session, int leafWorkersCount) {
		sqlTaskValuesHandler = new SqlTaskValuesHandler(session);
		leafTaskWorker = IWorker.size(leafWorkersCount);
		service = Executors.newSingleThreadExecutor();
	}

	public IWorking post(Node<SqlTaskValues> sqlTaskNode) {
		return IWorking.fromFuture(service.submit(() -> doTask(sqlTaskNode)));
	}

	public void doTask(Node<SqlTaskValues> sqlTaskNode) {
		// post all leaf tasks to leafTaskWorker
		System.out.println("run all leaf tasks");
		List<IWorking> leafWorkings = sqlTaskNode.leaves().stream()
				.<ITask>map(leaf -> () -> sqlTaskValuesHandler.handleLeaf(leaf))
				.map(leafTaskWorker::work)
				.collect(toList());

		// wait til them completed
		System.out.println("wait til them completed");
		leafWorkings.forEach(this::waitForCompletion);

		// merge sub tasks
		System.out.println("merging downloaded files...");
		sqlTaskNode.subs().forEach(sqlTaskValuesHandler::handleSub);
	}

	private void waitForCompletion(IWorking each) {
		try {
			each.waitForCompletion();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void close() {
		service.shutdown();
		leafTaskWorker.close();
	}
}
